package util

import (
	"bytes"
	rand2 "crypto/rand"
	"errors"
	"fmt"
	"longmen/server/config/global"
	"longmen/server/internal/rpc/tencentim/config"
	_const "longmen/server/pkg/common/helper/const"
	"math"
	"math/big"
	"math/rand"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	"unicode"

	"github.com/spf13/cast"
)

func CheckPwd(pwd string) bool {
	regRuler := "^[a-zA-Z0-9]{6,12}$" //数字，字母，6～12位
	regDigit := "^[0-9]{6,12}$"
	regLetter := "^[a-zA-Z]{6,12}$"
	// 正则调用规则
	reg := regexp.MustCompile(regRuler)
	regDightOnly := regexp.MustCompile(regDigit)
	regLetterOnly := regexp.MustCompile(regLetter)

	// 返回 MatchString 是否匹配
	if reg.MatchString(pwd) &&
		!regDightOnly.MatchString(pwd) &&
		!regLetterOnly.MatchString(pwd) {
		return true
	}
	return false
}
func CheckMobile(phone string) error {
	if global.Lang.GetLang() != _const.LangChinese {
		return nil
	}
	// 匹配规则
	// ^1第一位为一
	// [345789]{1} 后接一位345789 的数字
	// \\d \d的转义 表示数字 {9} 接9位
	// $ 结束符
	regRuler := "^1[3456789]{1}\\d{9}$"

	// 正则调用规则
	reg := regexp.MustCompile(regRuler)

	// 返回 MatchString 是否匹配
	if reg.MatchString(phone) {
		return nil
	}

	return errors.New("请输入正确的手机号")
}

//返回输入的字符串的字数，汉字和中文标点算 1 个字数，英文和其他字符 2 个算 1 个字数，不足 1 个算 1个
func GetStrLength(str string) float64 {
	var total float64
	reg := regexp.MustCompile("/·|，|。|《|》|‘|'|”|“|；|：|【|】|？|（|）|、/")
	for _, r := range str {
		if unicode.Is(unicode.Scripts["Han"], r) || reg.Match([]byte(string(r))) {
			total = total + 1
		} else {
			total = total + 0.5
		}
	}
	return math.Ceil(total)
}

func GetImgLableUrl(lable string) []string {
	regexp2 := regexp.MustCompile("<img[^>]+src=\\\"(.*?)\\\"[^>]*>*?")
	match := regexp2.FindAllString(lable, -1)
	var rs []string
	if match != nil {
		for _, v := range match {
			ttt := regexp2.ReplaceAllString(v, "$1")
			rs = append(rs, ttt)
		}
	}
	return rs
}

//获取新闻内容的纯文本
func TrimHtml(src string) string {
	//将HTML标签全转换成小写
	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllStringFunc(src, strings.ToLower)
	//去除STYLE
	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
	src = re.ReplaceAllString(src, "")
	//去除SCRIPT
	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
	src = re.ReplaceAllString(src, "")
	//去除所有尖括号内的HTML代码，并换成换行符
	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllString(src, "\n")
	//去除连续的换行符
	re, _ = regexp.Compile("\\s{2,}")
	src = re.ReplaceAllString(src, "\n")
	src = strings.Replace(src, " ", "", -1)
	// 去除换行符
	src = strings.Replace(src, "\n", "", -1)
	src = strings.Replace(src, "", "", -1)
	return strings.TrimSpace(src)
}

//查看字符串在字符切片中是否存在
func StrIsExistInSlice(str string, slice []string) bool {
	for _, s := range slice {
		if str == s {
			return true
		}
	}
	return false
}

//从NAMI提供的推流地址中截取stream
func GetStreamFromPushUrl(url string) string {
	if url == "" {
		return url
	}
	s := strings.Split(url, "/")
	stream := s[len(s)-1]
	return stream
}

func S2I(s string) int {
	i, _ := strconv.Atoi(s)
	return i
}
func S2F(s string) float64 {
	f, _ := strconv.ParseFloat(s, 64)
	return f
}
func I2S(s int) string {
	return strconv.Itoa(s)
}

// 大写字母随机字符串
func RandUpperLettersSeq(n int) string {
	var letters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
	rand.Seed(time.Now().UnixNano())
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

// 字母数字随机字符串
func RandomLetterNumString(len int) string {
	var container string
	var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
	b := bytes.NewBufferString(str)
	length := b.Len()
	bigInt := big.NewInt(int64(length))
	for i := 0; i < len; i++ {
		randomInt, _ := rand2.Int(rand2.Reader, bigInt)
		container += string(str[randomInt.Int64()])
	}
	return container
}

func InArrayString(ids []string, id string) bool {
	for i := range ids {
		if id == ids[i] {
			return true
		}
	}
	return false
}

var MatchWeights sync.Map

//初始权重
func InitMatchWeights() {
	MatchWeights.Store("NBA", 100)
	MatchWeights.Store("英超", 99)
	MatchWeights.Store("西甲", 98)
	MatchWeights.Store("意甲", 97)
	MatchWeights.Store("德甲", 96)
	MatchWeights.Store("法甲", 95)
	MatchWeights.Store("中超", 94)
	MatchWeights.Store("欧冠", 93)
	MatchWeights.Store("亚冠", 92)
	MatchWeights.Store("CBA", 91)
}

//赛程权重
func GetMatchWeights(k string) int {
	n, ok := MatchWeights.Load(k)
	if !ok {
		return 0
	}
	return cast.ToInt(n)
}
func QuerySlice2Str(idSlice []int) string {
	var ss string
	for i := 0; i < len(idSlice); i++ {
		if i == 0 {
			s := fmt.Sprintf("%d", idSlice[i])
			ss += s
		} else {
			s := fmt.Sprintf(",%d", idSlice[i])
			ss += s
		}
	}
	return ss
}
func QueryInterfaceSlice2Str(idSlice []interface{}) string {
	var ss string
	for i := 0; i < len(idSlice); i++ {
		if i == 0 {
			s := fmt.Sprintf("%d", idSlice[i])
			ss += s
		} else {
			s := fmt.Sprintf(",%d", idSlice[i])
			ss += s
		}
	}
	return ss
}

func QuerySlice32Str(idSlice []int32) string {
	var ss string
	for i := 0; i < len(idSlice); i++ {
		if i == 0 {
			s := fmt.Sprintf("%d", idSlice[i])
			ss += s
		} else {
			s := fmt.Sprintf(",%d", idSlice[i])
			ss += s
		}
	}
	return ss
}

func QueryStrSliceToStr(slice []string) string {
	var ss string
	for i := 0; i < len(slice); i++ {
		if i == 0 {
			s := fmt.Sprintf("'%s'", slice[i])
			ss += s
		} else {
			s := fmt.Sprintf(",'%s'", slice[i])
			ss += s
		}
	}
	return ss
}
func QueryUint8Slice2Str(idSlice []uint8) string {
	var ss string
	for i := 0; i < len(idSlice); i++ {
		if i == 0 {
			s := fmt.Sprintf("%d", idSlice[i])
			ss += s
		} else {
			s := fmt.Sprintf(",%d", idSlice[i])
			ss += s
		}
	}
	return "(" + ss + ")"

}

var commandSlice sync.Map

func InitCallbackCommand() {
	commandSlice.Store(config.BeforeJoinRoom, 1)
	commandSlice.Store(config.RoomBeforeMsg, 1)
	commandSlice.Store(config.RoomAfterMsg, 1)
	commandSlice.Store(config.C2CBeforeMsg, 1)
	commandSlice.Store(config.QuitRoom, 1)
	commandSlice.Store(config.StateChange, 1)
}

func HasCallbackCommand(command string) bool {
	if _, ok := commandSlice.Load(command); ok {
		return true
	}
	return false
}

func GetMatchStatusCodeEn(sportsId int, status uint32) string {
	if sportsId == _const.CRICKET_BALL_SPORT_ID {
		return getCricketStatusEn(status)
	} else if sportsId == _const.FOOT_BALL_SPORT_ID {

	} else if sportsId == _const.FOOT_BALL_SPORT_ID {

	}
	return ""
}

func getCricketStatusEn(status uint32) string {
	var enStatus string
	switch status {
	case 0:
		enStatus = "Match exception"
	case 1:
		enStatus = "Not started"
	case 532:
		enStatus = "First set: Home team"
	case 533:
		enStatus = "First set: Away team"
	case 534:
		enStatus = "Second set: Home team"
	case 535:
		enStatus = "Second set: Away team"
	case 536:
		enStatus = "Awaiting Super Round"
	case 537:
		enStatus = "Super Round Home Team"
	case 538:
		enStatus = "Super Round Away Team"
	case 539:
		enStatus = "Super Round concluded"
	case 540:
		enStatus = "Inning Break"
	case 541:
		enStatus = "Super Round break"
	case 542:
		enStatus = "Midday Break"
	case 543:
		enStatus = "Tea Break"
	case 544:
		enStatus = "Finished (For The Day)"
	case 100:
		enStatus = "Full-Time"
	case 14:
		enStatus = "Postponed"
	case 15:
		enStatus = "Delay"
	case 16:
		enStatus = "Canceled"
	case 17:
		enStatus = "Interrupted"
	case 19:
		enStatus = "Abandoned"
	case 99:
		enStatus = "TBD"
	}
	return enStatus
}
